Fix iPhone web client layout, audio, and tap latency#247
Conversation
…ap defenses
iPhone players reported being unable to see history or the menu, and
when the menu was visible they could not tap cards to draw or play
them. Three issues compounded:
1. `.grid { display: grid }` in author CSS was overriding the UA
stylesheet's `[hidden] { display: none }`, so `gameShell.hidden = true`
did not actually hide the element. The login dialog backdrop happened
to mask this pre-login, but the cascade is wrong. Add
`[hidden] { display: none !important }` so the hidden attribute always
wins.
2. The History+Chat panel was bundled together with chat at the bottom of
it, sitting in column 2 on desktop and below the Game panel on mobile.
Players asked for History at the top, Game in the middle, Chat at the
bottom on phones. Split into three panels (history-panel / game-panel /
chat-panel) and use `grid-template-areas` so:
- Desktop keeps the same look: Game (left, full height), History
(top-right), Chat (bottom-right).
- Mobile: history → game → chat in a single column, all the way
down.
3. Tap reliability on iPhone: buttons inside scrollable lists could feel
unresponsive because of iOS Safari's touch-action heuristics and the
missing `cursor: pointer`. Add `cursor: pointer`,
`touch-action: manipulation`, `-webkit-tap-highlight-color`, and an
`:active` background on `.menu-item-touch` and `.actions-item-btn` for
visible tap feedback. Also add `-webkit-overflow-scrolling: touch` to
`.menu-list` so momentum scrolling does not eat taps.
4. Compact volume controls on mobile: drop `flex-direction: column` from
`.volume-controls` so the parent `.row` `flex-wrap: wrap` lets them
flow horizontally; header drops from 162px to 50–106px.
Bump web client version to 2026.05.03.2 to invalidate cached app.js on
iOS Safari.
Verified in playwright iPhone emulation:
- Portrait 390x844: History (y=269), Game with full menu (y=359), Chat
(y=719) all stack cleanly.
- Landscape 844x390: same order, all fits in 390px height.
- Desktop 1280x800: Game on left (full height), History top-right, Chat
bottom-right.
- Click handler verified firing on .menu-item-touch buttons.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Reviewed and validated on the merge ref. Most of this is solid work — the Desktop screen-reader/Tab order regressionThe previous commit on these files (
That commit used Net effect:
For this project — The clean fixKeep the original DOM order (Game, History, Chat) and use If you really want History first in the DOMFocus management can soften the initial-arrival case but doesn't substitute for DOM order: <section id="game-panel" class="panel game-panel" tabindex="-1">…</section>gameShell.hidden = false;
document.getElementById("game-panel").focus();This makes the screen reader announce "Game, heading level 2…" right when the shell appears, instead of starting at History. You could do the same on server state changes that return the turn to the user — focus the actions list so the new menu is announced immediately. The limit: browse mode (NVDA, JAWS) and VoiceOver's virtual cursor walk DOM order, not focus. So when the user presses Auto-focusing on every server update is worse — it interrupts the user mid-sentence if they were reading the history log when their turn started. So focus management is worth layering on regardless (the initial-arrival announcement is genuinely helpful), but for fixing the regression specifically, the DOM-order fix is one-line cheaper and has no edge cases. Smaller notes (non-blocking)Redundant preload list. The
Muting handles both paths. Element-based effects use Happy to chat through the layout option you prefer. |
Summary
Fix the iPhone web client issues seen while playing Mile by Mile: hidden panels leaking through the login view, awkward mobile panel order, delayed sound effects, and slow touch activation of menu/card items.
[hidden]always wins over author display rules so hidden UI actually stays hidden.History -> Game -> Chatand desktop layout preserved.pointerupbefore playing activation audio, so card/item taps reach the server immediately.Audio()element for every effect on demand.2026.05.07.1for cache invalidation.Root Cause
On iPhone Safari/WebKit, sound effects were being loaded at the moment of playback via new media elements. Slow media startup could then delay or back up effect playback. Touch activation also selected the item and ran sound work before sending the menu packet, which made taps feel delayed when audio loading stalled.
Validation
node --check clients/web/audio.js.node --check clients/web/ui/menus.js.node --check clients/web/app.js.git diff --check.